package com.kgcx.oagateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.kgcx.common.bean.ReturnData;
import com.kgcx.common.client.organization.WebUserClient;
import com.kgcx.common.client.organization.pojo.EmployeeCity;
import com.kgcx.common.utils.CollectionUtils;
import com.kgcx.common.utils.IpUtils;
import com.kgcx.common.utils.TokenUtils;
import com.kgcx.oagateway.service.TokenService;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Component
@Slf4j
public class TokenFilter extends ZuulFilter {
    @Value("${kgcx.token.enable:true}")
    private boolean tokenEnable;
    @Autowired
    private TokenService tokenService;
    @Resource
    private WebUserClient webUserClient;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String agent = request.getHeader("User-Agent");
        String ipAddr = IpUtils.getIpAddr(request);
        log.info("请求到达agent:{},ip:{}, ", agent, ipAddr);

        if (tokenEnable) {
            String servletPath = request.getServletPath();
            log.info("请求servletPath：{}", servletPath);
            if (ArrayUtils.contains(TokenUtils.TOKEN_SKIP_PATH, servletPath) || isActuatorEndpoint(servletPath)) {
                log.info("无需鉴权：{}", servletPath);
                return false;
            }
            log.info("需要鉴权：{}", servletPath);
            return true;
        }
        return false;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String token = request.getHeader("token");
        log.info("run token {}", token);
        String returnInfo;
        if (StringUtils.isBlank(token)) {
            returnInfo = "token验证失败";
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.SC_OK);
            ctx.getResponse().setContentType(ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8).toString());
            ctx.setResponseBody(JSONObject.toJSONString(new ReturnData<>("-99", returnInfo)));
            log.error("token验证失败,token=" + token);
            return null;
        }
        Claims claims = TokenUtils.getClaims(token);
        String subject = claims.getSubject();
        String id = claims.getId();
        String servletPath = request.getServletPath();
        log.info("run 请求servletPath：{}", servletPath);
        try {
            if (!tokenService.validateToken(token, subject, id)) {
                returnInfo = "token验证失败";
                ctx.setSendZuulResponse(false);
                ctx.setResponseStatusCode(HttpStatus.SC_OK);
                ctx.getResponse().setContentType(ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8).toString());
                ctx.setResponseBody(JSONObject.toJSONString(new ReturnData<>("-99", returnInfo)));
                log.error("token验证失败,token=" + token);
                return null;
            }
        } catch (ExpiredJwtException e) {
            returnInfo = "token过期";
            log.error(returnInfo, e);
        } catch (Exception e) {
            returnInfo = "内部错误";
            log.error(returnInfo, e);
        }

        // 设置用户城市数据权限
        List<String> cityList = new ArrayList<>();
        // 验证数据权限
        List<EmployeeCity> employeeCityList = webUserClient.getCityCodeByAccount(id);
        Map<String, String[]> parameterMap = ctx.getRequest().getParameterMap();
        Map<String, List<String>> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(employeeCityList)) {
            if (null != employeeCityList && employeeCityList.size() > 0) {
                for (EmployeeCity employeeCity : employeeCityList) {
                    cityList.add(employeeCity.getCityCode());
                    log.info("cityList={}", employeeCity.getCityCode());
                }
                if (MapUtils.isNotEmpty(parameterMap)) {
                    parameterMap.forEach((k, v) -> {
                        map.put(k, Arrays.asList(v));
                    });
                }
                map.put("cityIds", cityList);
                ctx.setRequestQueryParams(map);
            }
        }
//        List<String> userIds = new ArrayList<>();
//        if (TokenUtils.TOKEN_SUBJECT_WEBUSER.equals(subject)) {
//        		userIds.add(String.valueOf(kid));
//        	if (MapUtils.isNotEmpty(parameterMap)) {
//                parameterMap.forEach((k, v) -> {
//                    map.put(k, Arrays.asList(v));
//                });
//            }
//            map.put("oaUserId", userIds);
//            ctx.setRequestQueryParams(map);
//      }
        return null;
    }

    private boolean isActuatorEndpoint(String path) {
        return StringUtils.startsWithIgnoreCase(path, "/actuator/");
    }
}
